﻿using System;
using System.Drawing;
using System.Linq;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Model.Email;
using log4net;

namespace Kaleida.ServiceMonitor.Model
{
    public class ThresholdChangeEmailer : IServiceMonExtension
    {
        private static readonly ILog log = LogManager.GetLogger(typeof (ThresholdChangeEmailer));
        private readonly Monitor monitor;
    	[CanBeNull]private ScriptEmailSender emailSender;
        private Color mostRecentColour;
        readonly NotificationMessageBuilder builder = new NotificationMessageBuilder();

        public ThresholdChangeEmailer([NotNull] Monitor monitor)
        {
            if (monitor == null) throw new ArgumentNullException("monitor");
			
            this.monitor = monitor;
            UpdateMostRecentSeverityLevel();
        }

        public void ScriptCompilationComplete(ScriptCompilationCompleteEventArgs args)
        {
        }

        public void OnStartedMonitoring()
        {

			var recipients = monitor.CompiledModule.EmailOnThresholdChangeRecipients;
            if (recipients.Any())
            {
				var scriptName = monitor.CompiledModule.Name;
                emailSender = new ScriptEmailSender(scriptName, recipients);
				emailSender.Configure(monitor.Application.Configuration);
            }
        }

        public void OnStoppedMonitoring()
        {
        }

        public void OnOperationSuccessful(OperationSuccessfulEventArgs operationSuccessfulEventArgs)
        {
            SendEmailIfChangeInSeverity();
        }

        public void OnOperationFailed(OperationFailedEventArgs operationFailedEventArgs)
        {
            SendEmailIfChangeInSeverity();
        }

        public void OnClearFailures()
        {
            SendEmailIfChangeInSeverity();
        }

        public void OnScheduledTimeTick(MinuteTimerTickEventArgs eventArgs)
        {
        }

        private void SendEmailIfChangeInSeverity()
        {
            var message = BuildMessageIfChangeInSeverity();

			if (message != null && emailSender != null)
			{
                TrySendEmailAndLog(message);
			}
        }

        private void TrySendEmailAndLog(NotificationMessage message)
        {
            if (emailSender == null) throw new InvalidOperationException("ScriptEmailSender has not been set");
            log.DebugFormat("Sending email from monitor {0} for module {1} ({2})", monitor.Id, monitor.CompiledModule.Name, monitor.CompiledModule.Id);
            emailSender.TrySendEmail(message);
            log.DebugFormat("Sent email from monitor {0} for module {1} ({2})", monitor.Id, monitor.CompiledModule.Name, monitor.CompiledModule.Id);
        }

        [CanBeNull]
		private NotificationMessage BuildMessageIfChangeInSeverity()
        {
            lock (this)
            {
                var newColour = monitor.CompiledModule.ColourationStrategy.GetNotificationColour(monitor.State);

                if (newColour != mostRecentColour)
                {
                    var message = builder.BuildThresholdChangeSummary(monitor, mostRecentColour);
                    UpdateMostRecentSeverityLevel();
                    return message;
                }
                return null;
            }
        }

        private void UpdateMostRecentSeverityLevel()
        {
            mostRecentColour = monitor.CompiledModule.ColourationStrategy.GetNotificationColour(monitor.State);
        }
	}
}
